using CfgTable;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using NetProtocol.POD;
using System.Collections.Generic;

namespace IQIGame.Onigao.GamePlay
{

    public class Pet : IReusableClass
    {
        /// <summary>
        ///  唯一id
        /// </summary>
		public long id { get; private set; }
        /// <summary>
        /// 配置id
        /// </summary>
        public int cid { get; private set; }
        /// <summary>
        /// 创建时间(毫秒时间戳)
        /// </summary>
        public long createTime { get; private set; }
        /// <summary>
        /// 自定义名字，为空则显式默认名
        /// </summary>
        protected string name { get; private set; }
        /// <summary>
        /// 等级
        /// </summary>
        public int level { get; private set; }
        /// <summary>
        /// 当前等级经验
        /// </summary>
        public int exp { get; private set; }
        /// <summary>
        /// 是否锁定状态
        /// </summary>
        public bool isLock { get; private set; }
        /// <summary>
        /// 道具解锁的技能槽数量
        /// </summary>
        public int unlockSlot { get; private set; }
        /// <summary>
        /// 随机属性组1 -- 由于每组长度不一定相同，分开存放
        /// </summary>
        protected List<int> randAttrGroup1 { get; private set; }
        /// <summary>
        /// 随机属性组2
        /// </summary>
        protected List<int> randAttrGroup2 { get; private set; }
        /// <summary>
        /// 随机属性组3
        /// </summary>
        protected List<int> randAttrGroup3 { get; private set; }
        /// <summary>
        /// 装备的随机属性
        /// </summary>
        protected List<int> usingRandAttrs { get; private set; }

        /// <summary>
        /// 最终属性 -- 全发	
        /// </summary>
        public int[] attrs { get; private set; } = null;

        #region 配置 && 逻辑
        private CfgPet _cfgData = null;
        public CfgPet cfgData
        {
            get
            {
                if (this._cfgData == null && this.cid > 0)
                {
                    this._cfgData = TableCenter.pet.Get(this.cid);
                }
                return this._cfgData;
            }
        }

        private CfgPetLevel _cfgLevel = null;
        public CfgPetLevel cfgLevel
        {
            get
            {
                if (this.level > 0 && (this._cfgLevel == null || this._cfgLevel.Id != this.level))
                {
                    this._cfgLevel = TableCenter.petLevel.Get(this.level);
                }
                return this._cfgLevel;
            }
        }

        private CfgPetLevel _cfgMaxLevel = null;
        public CfgPetLevel cfgMaxLevel
        {
            get
            {
                if (this._cfgMaxLevel == null && this.cid > 0)
                {
                    var cfg = this.cfgData;
                    this._cfgMaxLevel = TableCenter.petLevel.Get(cfg.LevelLimit);
                }
                return this._cfgMaxLevel;
            }
        }

        private SkillBaseData _skillData = null;
        public SkillBaseData skillData
        {
            get
            {
                if (this._skillData == null && this.cid > 0)
                {
                    var cfg = this.cfgData;
                    this._skillData = SkillBaseData.NewFromPool().Sync(cfg.SkillID, 1);
                }
                return this._skillData;
            }
        }

        public IReadOnlyList<int> GetPabilityGroupList(int index)
        {
            return this._GetPabilityGroupList(index);
        }

        private List<int> _GetPabilityGroupList(int index)
        {
            return index switch
            {
                1 => this.randAttrGroup2,
                2 => this.randAttrGroup3,
                _ => this.randAttrGroup1,
            };
        }

        public int GetPabilityGroupIndex(int pabilityAttributeCid)
        {
            for (int i = 0; i < 3; i++)
            {
                var list = this._GetPabilityGroupList(i);
                if (list.Contains(pabilityAttributeCid))
                    return i;
            }
            return -1;
        }

        public HeroData currWearer => GameDataCenter.PlayerData.hero.GetPetWearer(this.id);

        public void UpdataLockState(bool isLock)
        {
            this.isLock = isLock;
        }

        public void UpdateName(string name)
        {
            this.name = name;
        }

        public string GetName()
        {
            string name = this.name;
            if (string.IsNullOrEmpty(name))
            {
                var cfg = this.cfgData;
                name = cfg.Name;
            }
            return name;
        }

        public void IncreaseUnlockSlot()
        {
            this.unlockSlot++;
        }

        public int GetUsedSlotCount()
        {
            int cnt = 0;
            foreach (var cid in this.usingRandAttrs)
            {
                var cfg = TableCenter.pabilityAttribute.Get(cid);
                cnt += cfg.PetSlotCost;
            }
            return cnt;
        }

        public bool ContainsUsingPabilityAttribute(int pabilityAttributeCid)
        {
            return this.usingRandAttrs.Contains(pabilityAttributeCid);
        }

        public void AddUsingPabilityAttribute(int pabilityAttributeCid)
        {
            bool isContains = this.usingRandAttrs.Contains(pabilityAttributeCid);
            if (!isContains)
                this.usingRandAttrs.Add(pabilityAttributeCid);
        }

        public void RemoveUsingPabilityAttribute(int pabilityAttributeCid)
        {
            this.usingRandAttrs.Remove(pabilityAttributeCid);
        }
        #endregion

        public Pet Sync(PetPOD pod)
        {
            this.id = pod.id;
            this.cid = pod.cid;
            this.createTime = pod.createTime;
            this.name = pod.name;
            this.level = pod.level;
            this.exp = pod.exp;
            this.isLock = pod.isLock;
            this.unlockSlot = pod.unlockSlot;
            this.attrs = pod.attrs;

            this.SyncList(pod.unsafe_randAttrGroup1, this.randAttrGroup1);
            this.SyncList(pod.unsafe_randAttrGroup2, this.randAttrGroup2);
            this.SyncList(pod.unsafe_randAttrGroup3, this.randAttrGroup3);
            this.SyncList(pod.unsafe_usingRandAttrs, this.usingRandAttrs);
            return this;
        }

        private void InitList()
        {
            if (this.randAttrGroup1 != null)
            {
                return;
            }
            this.randAttrGroup1 = ListPool<int>.Get();
            this.randAttrGroup2 = ListPool<int>.Get();
            this.randAttrGroup3 = ListPool<int>.Get();
            this.usingRandAttrs = ListPool<int>.Get();
        }

        private void SyncList(List<int> orgList, List<int> destList)
        {
            destList.Clear();
            if (orgList == null || orgList.Count == 0)
                return;
            foreach (int val in orgList)
            {
                destList.Add(val);
            }
        }

        public void Clear()
        {
            this.id = 0;
            this.cid = 0;
            this.createTime = 0;
            this.name = null;
            this.level = 0;
            this.exp = 0;
            this.isLock = false;
            this.unlockSlot = 0;
            this.attrs = null;

            this.RebackList();

            this.ClearLogicData();
        }

        private void RebackList()
        {
            if (this.randAttrGroup1 != null)
            {
                ListPool<int>.Put(this.randAttrGroup1);
                ListPool<int>.Put(this.randAttrGroup2);
                ListPool<int>.Put(this.randAttrGroup3);
                ListPool<int>.Put(this.usingRandAttrs);

            }
            this.randAttrGroup1 = null;
            this.randAttrGroup2 = null;
            this.randAttrGroup3 = null;
            this.usingRandAttrs = null;
        }

        private void ClearLogicData()
        {
            this._cfgData = null;
            this._cfgLevel = null;
            this._cfgMaxLevel = null;
            this._skillData = null;
        }

        #region 对象池
        public uint MaxStore => 1;

        public void OnReset()
        {
            this.Clear();
        }

        public void Put2Pool()
        {
            ClassPool<Pet>.Put(this);
        }

        static public Pet NewFromPool()
        {
            Pet pet = ClassPool<Pet>.Get();
            pet.InitList();
            return pet;
        }
        #endregion

        static public Pet ConvertBy(PetPOD pod)
        {
            var pet = NewFromPool().Sync(pod);
            return pet;
        }
    }

    public class PetModuleData
    {
        protected Dictionary<long, Pet> dicPet { get; private set; } = new(16);

        public int bagCapacity { get; private set; } = 0;

        public int petCount => this.dicPet.Count;

        public PetModuleData(int petBagCapacity)
        {
            this.bagCapacity = petBagCapacity;
        }

        public void Clear()
        {
            foreach (var pet in this.dicPet.Values)
            {
                pet.Put2Pool();
            }
            this.dicPet.Clear();
            this.bagCapacity = 0;
        }


        public bool TryGetValue(long id, out Pet outPet)
        {
            return this.dicPet.TryGetValue(id, out outPet);
        }

        public bool ContainsKey(long id)
        {
            return this.dicPet.ContainsKey(id);
        }

        public void Put(Pet pet)
        {
            this.dicPet[pet.id] = pet;
        }

        public bool Remove(long id)
        {
            return this.dicPet.Remove(id);
        }

        public bool Remove(long id, out Pet pet)
        {
            return this.dicPet.Remove(id, out pet);
        }

        public void UpdateBagCapacity(int bagCapacity)
        {
            this.bagCapacity = bagCapacity;
        }

        public List<Pet> GetPetList()
        {
            List<Pet> list = new(this.petCount);
            list.AddRange(this.dicPet.Values);
            return list;
        }
    }
}
